<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>QeePHP 应用开发权威指南</title>
<link href="css/base.css" rel="stylesheet" type="text/css">
</head>
<body>

<div id="page">


<div class="guide-section">

  <div class="guide-header">
    <span class="nav">
      <a href="http://qee13.com/app/?action=docs">文档索引</a>
      &raquo;
      <a href="index.html">QeePHP 应用开发权威指南</a>
      &raquo;
      <a href="node-form.html">表单控件</a>
      &raquo;
      处理数据    </span>
  </div>

  <div class="guide-section-details formatted">
    
<h1>用表单处理提交数据</h1>

<p>当用户通过浏览器提交数据后，我们可以使用 QForm
来对提交数据进行过滤和验证。</p>

<h2>定义表单过滤器</h2>

<p>在表单对象中，每一个元素可以保存一个或多个值。因此为表单元素指定过滤器，可以让表单对象在处理数据时自动完成对输入数据的过滤。</p>

<pre class="python code">username:
  <span
class="co1"># 用 _filters 指定元素的过滤器</span>
  _filters: <span
class="st0">&quot;trim, strtolower&quot;</span></pre>

<p>每一个过滤器的名字要么是一个全局函数，要么是一个类的静态方法。例如：</p>

<pre class="python code">username:
  _filters: <span
class="st0">&quot;my_filter_func, MyClass::myFilterMethod&quot;</span></pre>

<p>全局函数可以是 PHP
内置的函数，也可以是开发者自己编写的函数。</p>

<p>除了通过配置文件指定过滤器，还可以使用编码方式指定表单元素的过滤器。</p>

<pre class="php code"><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">add</span><span
class="br0">&#40;</span>QForm<span class="sy0">::</span><span
class="me2">ELEMENT</span><span class="sy0">,</span> <span
class="st_h">'username'</span><span class="br0">&#41;</span>
     <span
class="sy0">-&gt;</span><span class="me1">addFilters</span><span
class="br0">&#40;</span><span class="st_h">'trim, strtolower'</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>如果是需要附加参数的过滤器
，则必须采用下面的格式：</p>

<pre class="php code"><span class="re0">$element</span><span
class="sy0">-&gt;</span><span class="me1">addFilters</span><span
class="br0">&#40;</span><span class="kw3">array</span><span
class="br0">&#40;</span>
    <span class="kw3">array</span><span
class="br0">&#40;</span><span class="st_h">'substr'</span><span
class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span
class="nu0">5</span><span class="br0">&#41;</span><span
class="sy0">,</span>
    <span class="st_h">'strtolower'</span><span
class="sy0">,</span>
<span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<h2>定义表单验证规则</h2>

<p>过滤器可以将输入数据进行格式化，而验证则用来保证数据符合预期的要求。</p>

<pre class="python code">username:
  <span
class="co1"># 用 _validations 指定验证规则</span>
  _validations:
    - <span
class="st0">&quot;is_alnum&quot;</span>, <span
class="st0">&quot;用户名只能使用26个字母和数字&quot;</span>
    - <span
class="st0">&quot;min_length&quot;</span>, <span class="nu0">5</span>, <span
class="st0">&quot;用户名至少需要5个字符&quot;</span>
    - <span
class="st0">&quot;max_length&quot;</span>, <span class="nu0">15</span>, <span
class="st0">&quot;用户名不能超过15个字符&quot;</span></pre>

<p>上述每一条验证规则第一部分都是用于验证的方法，可以是
QValidator 类的验证方法，或者全局函数和类静态方法。</p>

<p>例如：</p>

<pre class="python code">username:
  _validations:
    - <span
class="st0">&quot;is_int&quot;</span>, <span
class="st0">&quot;使用 PHP 内置函数进行验证&quot;</span>
    - <span
class="st0">&quot;my_validate_func&quot;</span>, <span
class="st0">&quot;附加参数&quot;</span>, <span
class="st0">&quot;自定义验证函数&quot;</span>
    - <span
class="st0">&quot;MyClass::validateMethod&quot;</span>, <span
class="st0">&quot;附加参数1&quot;</span>, <span
class="st0">&quot;附加参数2&quot;</span>, <span
class="st0">&quot;用于验证的类静态方法&quot;</span></pre>

<p>验证规则的第二部分则是需要传递给验证方法的附加参数，例如
min_length
这个验证方法要求指定值的最短长度。附加参数的个数是不定的，最后一个参数则总是验证失败时要显示的错误信息。</p>

<p>使用连贯接口为元素添加验证规则：</p>

<pre class="php code"><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">add</span><span
class="br0">&#40;</span>QForm<span class="sy0">::</span><span
class="me2">ELEMENT</span><span class="sy0">,</span> <span
class="st_h">'username'</span><span class="br0">&#41;</span>
     <span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span><span class="st_h">'is_alnum'</span><span
class="sy0">,</span> <span
class="st_h">'用户名只能使用26个字母和数字'</span><span
class="br0">&#41;</span>
     <span class="sy0">-&gt;</span><span
class="me1">addValidations</span><span class="br0">&#40;</span><span
class="st_h">'min_length'</span><span class="sy0">,</span> <span
class="nu0">5</span><span class="sy0">,</span> <span
class="st_h">'用户名至少需要5个字符'</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>批量添加验证规则：</p>

<pre class="php code"><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">add</span><span
class="br0">&#40;</span>QForm<span class="sy0">::</span><span
class="me2">ELEMENT</span><span class="sy0">,</span> <span
class="st_h">'password'</span><span class="br0">&#41;</span>
     <span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span><span class="kw3">array</span><span
class="br0">&#40;</span>
         <span class="kw3">array</span><span
class="br0">&#40;</span><span class="st_h">'min_length'</span><span
class="sy0">,</span> <span class="nu0">6</span><span class="sy0">,</span> <span
class="st_h">'密码至少需要5个字符'</span><span
class="br0">&#41;</span><span class="sy0">,</span>
         <span
class="kw3">array</span><span class="br0">&#40;</span><span
class="st_h">'max_length'</span><span class="sy0">,</span> <span
class="nu0">30</span><span class="sy0">,</span> <span
class="st_h">'密码最多30个字符'</span><span class="br0">&#41;</span><span
class="sy0">,</span>
     <span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<h2>用表单对象处理输入数据</h2>

<p>设置好表单的过滤器和验证规则后，就可以将数据导入表单对象并进行处理了。</p>

<p>将数据导入表单对象，并进行过滤和验证：</p>

<pre class="php code"><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">validate</span><span
class="br0">&#40;</span><span class="re0">$_POST</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>validate() 方法完成三项工作：</p>

<ol>
	<li>将数据导入表单对象</li>

	<li>对数据进行过滤和验证</li>

	<li>如果所有数据验证都通过，返回 true，否则返回 false</li>
</ol>

<p>表单处理过程示例：</p>

<pre class="php code"><span class="kw2">class</span> Controller_Posts <span
class="kw2">extends</span> Controller_Abstract
<span
class="br0">&#123;</span>
    <span
class="kw2">function</span> actionCreate<span class="br0">&#40;</span><span
class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span
class="re0">$form</span> <span class="sy0">=</span> <span
class="kw2">new</span> PostForm<span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span
class="co1">// 判断当前请求是否是 POST 请求</span>
        <span
class="kw1">if</span> <span class="br0">&#40;</span><span
class="re0">$this</span><span class="sy0">-&gt;</span>_context<span
class="sy0">-&gt;</span><span class="me1">isPOST</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span>
        <span
class="br0">&#123;</span>
            <span class="kw1">if</span> <span
class="br0">&#40;</span><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">validate</span><span
class="br0">&#40;</span><span class="re0">$_POST</span><span
class="br0">&#41;</span><span class="br0">&#41;</span>
            <span
class="br0">&#123;</span>
                <span
class="co1">// 验证通过，创建一个新的 Post 对象并保存</span>
                <span
class="re0">$post</span> <span class="sy0">=</span> <span
class="kw2">new</span> Post<span class="br0">&#40;</span><span
class="re0">$form</span><span class="sy0">-&gt;</span><span
class="me1">values</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
                <span class="re0">$post</span><span
class="sy0">-&gt;</span><span class="me1">save</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
&nbsp;
                <span
class="co1">// 重定向浏览器</span>
                <span
class="kw1">return</span> <span class="re0">$this</span><span
class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span>url<span
class="br0">&#40;</span><span class="st_h">'posts/show'</span><span
class="sy0">,</span> <span class="kw3">array</span><span
class="br0">&#40;</span><span class="st_h">'id'</span> <span
class="sy0">=&gt;</span> <span class="re0">$post</span><span
class="sy0">-&gt;</span><span class="me1">id</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
            <span class="br0">&#125;</span>
        <span
class="br0">&#125;</span>
&nbsp;
        <span class="re0">$this</span><span
class="sy0">-&gt;</span>_view<span class="br0">&#91;</span><span
class="st_h">'form'</span><span class="br0">&#93;</span> <span
class="sy0">=</span> <span class="re0">$form</span><span
class="sy0">;</span>
    <span class="br0">&#125;</span>
<span
class="br0">&#125;</span></pre>

<p>在上面的代码中，在验证失败时并没有进行处理，而是将错误显示等工作交给视图完成。</p>

<h2>在视图中显示表单验证错误信息</h2>

<p>视图中可以通过 isValid() 确认元素值是否验证通过，并用
errorMsg() 获得该元素所有的验证错误信息。</p>

<pre class="php code"><span class="kw2">&lt;?php</span> <span
class="kw3">echo</span> Q<span class="sy0">::</span><span
class="me2">control</span><span class="br0">&#40;</span><span
class="re0">$element</span><span class="sy0">-&gt;</span>_ui<span
class="sy0">,</span> <span class="re0">$id</span><span
class="sy0">,</span> <span class="re0">$element</span><span
class="sy0">-&gt;</span><span class="me1">attribs</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span> <span
class="kw2">?&gt;</span>
&nbsp;
<span class="kw2">&lt;?php</span> <span
class="kw1">if</span> <span class="br0">&#40;</span><span
class="sy0">!</span><span class="re0">$element</span><span
class="sy0">-&gt;</span><span class="me1">isValid</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">:</span> <span
class="kw2">?&gt;</span>
&lt;span class=&quot;error&quot;&gt;
  <span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="kw3">nl2br</span><span class="br0">&#40;</span>h<span
class="br0">&#40;</span><span class="kw3">implode</span><span
class="br0">&#40;</span><span class="st0">&quot;<span
class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span
class="re0">$element</span><span class="sy0">-&gt;</span><span
class="me1">errorMsg</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span> <span class="kw2">?&gt;</span>
&lt;/span&gt;
<span
class="kw2">&lt;?php</span> <span class="kw1">endif</span><span
class="sy0">;</span> <span class="kw2">?&gt;</span></pre>

<h2>配合模型使用表单</h2>

<p>大多数情况下，我们将输入数据导入表单，过滤和验证后再通过模型保存到数据库中。</p>

<p>由于模型可以定义验证规则，所以本着 DRY
原则，我们不应该在表单中把验证规则再定义一次。</p>

<pre class="php code"><span class="kw2">class</span> PostForm <span
class="kw2">extends</span> QForm
<span class="br0">&#123;</span>
    <span
class="kw2">function</span> __construct<span class="br0">&#40;</span><span
class="re0">$id</span> <span class="sy0">=</span> <span
class="kw2">null</span><span class="sy0">,</span> <span
class="re0">$action</span> <span class="sy0">=</span> <span
class="kw2">null</span><span class="sy0">,</span> <span
class="re0">$method</span> <span class="sy0">=</span> <span
class="kw2">null</span><span class="br0">&#41;</span>
    <span
class="br0">&#123;</span>
        parent<span
class="sy0">::</span>__construct<span class="br0">&#40;</span><span
class="re0">$id</span><span class="sy0">,</span> <span
class="re0">$action</span><span class="sy0">,</span> <span
class="re0">$method</span><span class="br0">&#41;</span><span
class="sy0">;</span>
        <span class="re0">$this</span><span
class="sy0">-&gt;</span><span class="me1">add</span><span
class="br0">&#40;</span>QForm<span class="sy0">::</span><span
class="me2">ELEMENT</span><span class="sy0">,</span> <span
class="st_h">'title'</span><span class="br0">&#41;</span><span
class="sy0">;</span>
                 <span class="sy0">-&gt;</span><span
class="me1">addFilter</span><span class="br0">&#40;</span><span
class="st_h">'trim'</span><span class="br0">&#41;</span>
                 <span
class="co1">// 将 Post 模型的验证规则指定给 title 元素</span>
                 <span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span>Post<span class="sy0">::</span><span
class="me2">meta</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
    <span class="br0">&#125;</span>
<span
class="br0">&#125;</span></pre>

<p>从模型批量设置验证规则：</p>

<pre class="php code"><span
class="co1">// 调用 QForm 对象的 addValidation() 方法</span>
<span
class="re0">$form</span><span class="sy0">-&gt;</span><span
class="me1">addValidation</span><span class="br0">&#40;</span>Post<span
class="sy0">::</span><span class="me2">meta</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>上述代码会将模型所有属性的验证规则指定给表单中的同名元素。</p>

<p>有必要时，可以进一步指定只导入哪些属性的验证规则：</p>

<pre class="php code"><span
class="co1">// 仅有 title 和 body 属性的验证规则会被导入表单的同名元素</span>
<span
class="re0">$form</span><span class="sy0">-&gt;</span><span
class="me1">addValidations</span><span class="br0">&#40;</span>Post<span
class="sy0">::</span><span class="me2">meta</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">,</span> <span class="st_h">'title, body'</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<h2>将表单数据传递给模型</h2>

<p>表单的数据通过验证后，需要传递给模型，才能最终保存到数据库：</p>

<pre class="php code"><span class="re0">$post</span> <span
class="sy0">=</span> <span class="kw2">new</span> Post<span
class="br0">&#40;</span><span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">values</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>表单对象的 values()
方法用来提取已经过滤和验证过的表单数据，因此可以放心的存入模型中。</p>

<p> </p>

<p> </p>

<p> </p>
$Id: form-data.texy 2009-03-10 07:48:18Z Tim13 $
  </div>

  <div class="guide-footer">

    <table border="0" width="100%">
      <tr>
        <td align="left" width="200">
                    &laquo;
          <a href="node-form-render.html">显示表单</a>
          
        </td>

        <td align="center">
          本章：<a href="node-form.html">表单控件</a>
          <br />
          <a href="index.html">返回索引页</a>
        </td>

        <td align="right" width="200">
                    <a href="node-form-states.html">不同状态的表单</a> 
          &raquo;
                  </td>
      </tr>
    </table>

  </div>

</div>


</div>

</body>
</html>


